Skip to content

[pull] main from MetaMask:main#78

Merged
pull[bot] merged 3 commits into
Reality2byte:mainfrom
MetaMask:main
Aug 18, 2025
Merged

[pull] main from MetaMask:main#78
pull[bot] merged 3 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Aug 18, 2025

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.3)

Can you help keep this open source service alive? 💖 Please sponsor : )

pnarayanaswamy and others added 3 commits August 18, 2025 12:35
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Adds a default mocks setup for all tests.

Each test now automatically includes a predefined set of default mocks.
Test-specific mocks can be added on top of these defaults. When a test
mocks an endpoint that is also in the default set, the test’s mock takes
precedence. This ensures consistent baseline mocks across the suite
while still allowing per-test customization.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:
[MMQA-851](https://consensyssoftware.atlassian.net/browse/MMQA-851)

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


[MMQA-851]:
https://consensyssoftware.atlassian.net/browse/MMQA-851?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
…imizations (#18430)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR implements WebSocket-based real-time data streaming for the
Perps feature, replacing the previous polling-based approach. The
implementation evolved significantly from the original plan to include
critical performance optimizations and architectural improvements that
eliminate unnecessary re-renders and provide flexible update control.

**Key improvements:**
1. **Pure WebSocket Architecture**: Migrated from hybrid REST/WebSocket
to pure WebSocket for all live data (prices, positions, orders, fills)
2. **Flexible Throttling**: Made throttling optional with smart defaults
- instant updates for user actions (orders/positions), throttled for
high-frequency data (prices)
3. **Re-render Optimization**: Created isolated leaf components for
frequently updating data to prevent parent component re-renders
4. **TP/SL Fix**: Fixed root cause of Take Profit/Stop Loss data not
displaying by extracting from `triggerPx` field instead of broken
`isPositionTpsl` flag
5. **WebSocket Pre-warming**: Pre-establishes positions and orders
subscriptions when entering Perps environment to eliminate empty initial
states

## **Changelog**

CHANGELOG entry: Fixed Perps live data updates and significantly
improved performance by implementing WebSocket streaming with optimized
re-rendering

**Latest fixes:**
- Eliminated duplicate WebSocket subscriptions by implementing shared
webData2 connection for positions and orders
- Single WebSocket connection now provides both positions (with TP/SL)
and orders data
- Fixed pre-warming to create persistent subscriptions that stay alive
throughout Perps session
- Pre-warm subscriptions now use no-op callbacks to maintain connections
and continuous caching
- Fixed reference counting with separate position/order subscriber
tracking to prevent premature disconnection

## **Related issues**

Fixes: Implementation of PR#3 from perps_stream_architecture_v3.md plan

## **Manual testing steps**

```gherkin
Feature: Perps WebSocket Streaming

  Scenario: User views live price updates without UI lag
    Given user is on the Perps Market Details view
    And market prices are changing rapidly

    When user observes the price display
    Then prices update smoothly every 1-2 seconds
    And parent components do not re-render
    And UI remains responsive

  Scenario: User places and cancels orders with instant feedback
    Given user has the Orders tab open in Market Details

    When user places a new order
    Then order appears instantly in the list without delay
    
    When user cancels an order
    Then order disappears instantly from the list

  Scenario: User views positions with TP/SL values
    Given user has open positions with Take Profit and Stop Loss set

    When user views the Positions tab
    Then TP/SL values are displayed correctly for each position
    And values update in real-time via WebSocket

  Scenario: Positions are available immediately on mount
    Given user navigates to Perps environment

    When any component requests positions data
    Then positions are available immediately from cache
    And there is no empty state for ~10 seconds
    And components render with data from the start

  Scenario: Funding countdown updates without parent re-renders
    Given user is viewing a market with funding payments

    When funding countdown timer ticks
    Then only the countdown text updates
    And parent components remain stable (no re-renders)
```

## **Screenshots/Recordings**

### **Before**
- Excessive re-renders every second from funding countdown
- 30-second delay for order cancellation updates
- TP/SL values not displaying (isPositionTpsl always false)
- Parent components re-rendering on every price update
- Empty positions array for ~10 seconds on initial mount

### **After**
- Isolated countdown component - no parent re-renders
- Instant order updates (0ms throttle)
- TP/SL values correctly extracted and displayed
- Leaf components handle updates without affecting parents
- Positions and orders available immediately from pre-warmed cache

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---

## Technical Details

### Files Changed Summary

**New Components (3):**
- `FundingCountdown` - Isolated timer component preventing parent
re-renders
- `LivePriceDisplay` - Real-time price display component
- `LivePriceHeader` - Market header with live price updates

**New Stream Hooks (4):**
- `usePerpsLiveOrders` - Real-time order updates (0ms default throttle)
- `usePerpsLivePositions` - Real-time position updates (0ms default
throttle)
- `usePerpsLivePrices` - Real-time price updates (1000ms default
throttle)
- `usePerpsLiveFills` - Real-time fill updates (0ms default throttle)

**Removed Polling Hooks (2):**
- `usePerpsOpenOrders` - Replaced by `usePerpsLiveOrders`
- `usePerpsPositions` - Replaced by `usePerpsLivePositions`

**Core Infrastructure:**
- `PerpsStreamManager` - Enhanced with optional throttling
- `HyperLiquidSubscriptionService` - Pure WebSocket implementation

### Performance Metrics

| Metric | Before | After | Improvement |
|--------|--------|-------|-------------|
| WebSocket Connections | N per component | 1 per data type | ~90%
reduction |
| Parent Re-renders | Every update | Never | 100% reduction |
| Order Update Latency | 30 seconds | Instant | 30s improvement |
| Price Update Frequency | Uncontrolled | 1-2 seconds | Balanced |

### Architecture Improvements

1. **Optional Throttling Pattern**
```typescript
// Instant updates for user actions
const orders = usePerpsLiveOrders({ throttleMs: 0 }); // default

// Throttled updates for high-frequency data
const prices = usePerpsLivePrices({ throttleMs: 1000 }); // default
```

2. **Leaf Component Pattern**
```typescript
// Before: Parent re-renders every second
<Text>{fundingCountdown}</Text>

// After: Only leaf component re-renders
<FundingCountdown />
```

3. **TP/SL Data Extraction**
```typescript
// Fixed: Extract from triggerPx instead of broken isPositionTpsl
if (order.triggerPx) {
  if (order.orderType?.includes('Take Profit')) {
    existing.takeProfitPrice = order.triggerPx;
  } else if (order.orderType?.includes('Stop')) {
    existing.stopLossPrice = order.triggerPx;
  }
}
```

4. **Persistent Pre-warming with Single Connection**
```typescript
// Pre-warm creates REAL subscriptions that persist throughout session
public prewarm(): () => void {
  // Creates subscription with no-op callback to keep connection alive
  this.prewarmUnsubscribe = this.subscribe({
    callback: () => {}, // Keeps connection alive for caching
    throttleMs: 0
  });
  return this.prewarmUnsubscribe; // Cleanup function for when leaving Perps
}
```

5. **Shared webData2 Subscription with Proper Reference Counting**
```typescript
// Separate counters for positions and orders prevent premature disconnection
private positionSubscriberCount = 0;
private orderSubscriberCount = 0;

// Only cleanup when BOTH have zero subscribers
private cleanupSharedWebData2Subscription(): void {
  const totalSubscribers = this.positionSubscriberCount + this.orderSubscriberCount;
  if (totalSubscribers <= 0 && this.sharedWebData2Subscription) {
    // Safe to disconnect - no subscribers left
  }
}
```

---------

Co-authored-by: Claude <noreply@anthropic.com>
@pull pull Bot locked and limited conversation to collaborators Aug 18, 2025
@pull pull Bot added the ⤵️ pull label Aug 18, 2025
@pull pull Bot merged commit 6fb3cb3 into Reality2byte:main Aug 18, 2025
9 of 44 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants